package com.sias.oj.service.impl;

import com.baomidou.mybatisplus.core.conditions.Wrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.sias.oj.common.ErrorCode;
import com.sias.oj.exception.BusinessException;
import com.sias.oj.mapper.PostFavourMapper;
import com.sias.oj.model.entity.Post;
import com.sias.oj.model.entity.PostFavour;
import com.sias.oj.model.entity.User;
import com.sias.oj.service.PostFavourService;
import com.sias.oj.service.PostService;
import org.springframework.aop.framework.AopContext;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;

/**
 * 帖子收藏服务实现
 *
 * @author <a href="https://github.com/sogra">程序员sogra</a>
 */
@Service
public class PostFavourServiceImpl extends ServiceImpl<PostFavourMapper, PostFavour>
        implements PostFavourService {

  @Resource
  private PostService postService;

  /**
   * 帖子收藏
   *
   * @param postId
   * @param loginUser
   * @return
   */
  @Override
  public int doPostFavour(long postId, User loginUser) {
    // 判断是否存在
    Post post = postService.getById(postId);
    if (post == null) {
      throw new BusinessException(ErrorCode.NOT_FOUND_ERROR);
    }
    // 是否已帖子收藏
    long userId = loginUser.getId();
    // 每个用户串行帖子收藏
    // 锁必须要包裹住事务方法
    PostFavourService postFavourService = (PostFavourService) AopContext.currentProxy();
    synchronized (String.valueOf(userId).intern()) {
      return postFavourService.doPostFavourInner(userId, postId);
    }
  }

  @Override
  public Page<Post> listFavourPostByPage(IPage<Post> page, Wrapper<Post> queryWrapper, long favourUserId) {
    if (favourUserId <= 0) {
      return new Page<>();
    }
    return baseMapper.listFavourPostByPage(page, queryWrapper, favourUserId);
  }

  /**
   * 封装了事务的方法
   *
   * @param userId
   * @param postId
   * @return
   */
  @Override
  @Transactional(rollbackFor = Exception.class)
  public int doPostFavourInner(long userId, long postId) {
    PostFavour postFavour = new PostFavour();
    postFavour.setUserId(userId);
    postFavour.setPostId(postId);
    QueryWrapper<PostFavour> postFavourQueryWrapper = new QueryWrapper<>(postFavour);
    PostFavour oldPostFavour = this.getOne(postFavourQueryWrapper);
    boolean result;
    // 已收藏
    if (oldPostFavour != null) {
      result = this.remove(postFavourQueryWrapper);
      if (result) {
        // 帖子收藏数 - 1
        result = postService.update()
                .eq("id", postId)
                .gt("favourNum", 0)
                .setSql("favourNum = favourNum - 1")
                .update();
        return result ? -1 : 0;
      } else {
        throw new BusinessException(ErrorCode.SYSTEM_ERROR);
      }
    } else {
      // 未帖子收藏
      result = this.save(postFavour);
      if (result) {
        // 帖子收藏数 + 1
        result = postService.update()
                .eq("id", postId)
                .setSql("favourNum = favourNum + 1")
                .update();
        return result ? 1 : 0;
      } else {
        throw new BusinessException(ErrorCode.SYSTEM_ERROR);
      }
    }
  }

}




